package com.feishi.core.socket.netty;


import com.feishi.core.analytic.assembler.BaseAssembler;
import com.feishi.core.socket.common.SocketDecoder;
import com.feishi.core.socket.common.SocketServer;
import com.feishi.core.socket.common.lifecycle.SocketSession;
import com.feishi.core.socket.common.decoder.SplitDecoder;
import com.feishi.core.socket.netty.handler.NettyDecoderHandler;
import com.feishi.core.socket.netty.handler.NettyHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslHandler;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.util.ArrayList;
import java.util.List;

public abstract class NettyServer<T extends BaseAssembler> extends SocketServer<T> {

	private  ChannelHandlerAdapter adapter=null;
	private SSLEngine engine;
	private boolean enableSSL;



	public NettyServer() {
		init();
	}

	public NettyServer(ChannelHandlerAdapter adapter) {
		this.adapter=adapter;
	}

	public void startServer() {

		EventLoopGroup boss = new NioEventLoopGroup();
		EventLoopGroup worker = new NioEventLoopGroup();

		try {

			ServerBootstrap bootstrap = new ServerBootstrap();

			bootstrap.group(boss, worker)
					.channel(NioServerSocketChannel.class)
					.option(ChannelOption.SO_BACKLOG, 1024)// 连接数
					.option(ChannelOption.TCP_NODELAY, true) // 不延迟，消息立即发送
					.childOption(ChannelOption.SO_KEEPALIVE, true) // 长连接
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel socketChannel) throws Exception {
							ChannelPipeline pipe = socketChannel.pipeline();
							if (enableSSL){
								pipe.addLast(new SslHandler(engine));
							}
							SocketSession session=new SocketSession(application);
							for (ChannelHandlerFactory channelHandlerFactory:handlerFactoryList) {
								pipe.addLast(channelHandlerFactory.getChannelHandler(session));
							}
						}
					});
			ChannelFuture f = bootstrap.bind(getPort()).sync();
			if (f.isSuccess()) {
				System.out.println("启动Netty服务成功，端口号：" + getPort());
			}
			// 关闭连接
			f.channel().closeFuture().sync();

		} catch (Exception e) {
			System.err.println("启动Netty服务异常，异常信息：" + e.getMessage());
			e.printStackTrace();
		} finally {
			boss.shutdownGracefully();
			worker.shutdownGracefully();
		}
	}


	public void enableSSL(SSLContext context){
		if(context==null){
			return;
		}

		this.engine = context.createSSLEngine();
		engine.setUseClientMode(false);
		this.enableSSL=true;
	}
	public void disableSSL(SSLContext context){
		this.enableSSL=false;
	}

	protected List<ChannelHandlerFactory> handlerFactoryList=new ArrayList<ChannelHandlerFactory>();


	public void addChannelHandlerFactory(ChannelHandlerFactory channelHandlerFactory){
		handlerFactoryList.add(channelHandlerFactory);
	}
	public void addChannelHandlerFactoryAtFirst(ChannelHandlerFactory channelHandlerFactory){
		handlerFactoryList.add(0,channelHandlerFactory);
	}
	public void clearChannelHandlerFactory(){
		handlerFactoryList.clear();
	}

	public void init(){
		this.addChannelHandlerFactoryAtFirst((SocketSession session)->new NettyDecoderHandler(decoder));
		this.addChannelHandlerFactory((SocketSession session)->new NettyHandler(session));
	}
	private SocketDecoder<T> decoder=new SplitDecoder('\n','\\');

	public SocketDecoder<T> getDecoder() {
		return decoder;
	}

	public void setDecoder(SocketDecoder<T> decoder) {
		this.decoder = decoder;
	}
}
